home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / util / multifin / monproc2.sit / Monitor Process Folder / The Source Code / moni.c next >
C/C++ Source or Header  |  1991-09-16  |  51KB  |  1,602 lines

  1. /********************************************************************************/
  2. /*                                                                                */
  3. /* This program will display a list of current processes that exist on the        */
  4. /* Macintosh in use (running under System 7) by using the Process Manager which    */
  5. /* is new to the Macintosh Toolbox in System 7.                                    */
  6. /*                                                                                */
  7. /* Programmer:        Matthew B. Evans (alias Spaceship)                            */
  8. /* Date:            August 1, 1991                                                */
  9. /* System:            Macintosh II, PMMU, 13MB virtual, one Apple 13" monitor.    */
  10. /* Devl System:        Symantec's THINK C v5.0                                        */
  11. /* Notes:            This program makes use of several libraries written by        */
  12. /*                    myself.  They only aid in shortening code, they do not        */
  13. /*                    affect the theory of the code.                                */
  14. /*                                                                                */
  15. /********************************************************************************/
  16. /*                                                                                */
  17. /* Future Enhancements                                                            */
  18. /* -------------------                                                            */
  19. /*                                                                                */
  20. /* o Put ticks into minutes and seconds.                                        */
  21. /* o Draw icons?                                                                */
  22. /* o Add in file location.                                                        */
  23. /* o Fix CPU time.                                                                */
  24. /*                                                                                */
  25. /********************************************************************************/
  26.  
  27. #include    <misclib.h>                    /* Used for InitToolbox() */
  28. #include    <dialoglib.h>                /* Helps with alerts and dialogs */
  29. #include    <ListBox.h>                    /* My Listbox Manager */
  30. #include    <ResHelper.h>                /* Shortens code to manipulate resources */
  31.  
  32. #include    <stdio.h>                    /* ANSI C includes */
  33.  
  34. /********************************************************************************/
  35.  
  36.  
  37. /* Defines and macros */
  38.  
  39. #define        MONITOR_WIND_ID            2000        /* WIND/DITL resource IDs */
  40.  
  41. #define        ABOUT_DLOG_ID            3000        /* DLOG/DITL resource IDs */
  42. #define        PREFS_DLOG_ID            3001
  43. #define        INFO_DLOG_ID            3002
  44.  
  45. #define        ERROR_ALERT_ID            1000        /* ALRT/DITL resource IDs */
  46. #define        BAD_RESOURCES            1001
  47.  
  48. #define        PREF_REFRESH_ITEM        3            /* PREFS_DLOG_ID DITL numbers */
  49. #define        PREF_DEF_WINDOW            7
  50. #define        PREF_AUTO_UPDATE        8
  51. #define        PREF_HIDE_IN_BACK        9
  52. #define        PREF_SAVE_PREFS            11
  53.  
  54. #define        INFO_NAME                13            /* INFO_DLOG_ID DITL numbers */
  55. #define        INFO_PSN                14
  56. #define        INFO_TYPE                15
  57. #define        INFO_SIGNATURE            16
  58. #define        INFO_ADDRESS            17
  59. #define        INFO_SIZE                18
  60. #define        INFO_FREEMEM            19
  61. #define        INFO_LAUNCHER            20
  62. #define        INFO_DATE                21
  63. #define        INFO_CPU_TIME            22
  64. #define        INFO_LOCATION            23
  65. #define        INFO_DA                    24
  66. #define        INFO_MULTI_LAUNCH        25
  67. #define        INFO_SUSPEND_RESUME        26
  68. #define        INFO_CAN_BACKGROUND        27
  69. #define        INFO_ACTIVATE_FGSWITCH    28
  70. #define        INFO_ONLY_BACKGROUND    29
  71. #define        INFO_GET_FRONT_CLICKS    30
  72. #define        INFO_GET_APP_DIED_EVT    31
  73. #define        INFO_32BIT_COMPATIBLE    32
  74. #define        INFO_HLEVENT_AWARE        33
  75. #define        INFO_LOCAL_REMOTE_HLE    34
  76. #define        INFO_STATIONERY_AWARE    35
  77. #define        INFO_TEXTEDIT_SERVICES    36
  78. #define        INFO_SYSTEM                38
  79.  
  80. #define        ERROR_STRINGS_ID        1000        /* 'STR#' resources */
  81.  
  82. #define        STR_SYSTEM7_REQUIRED    1            /* ERROR_STRINGS_ID string indexes */
  83. #define        STR_CANT_GET_RESOURCES    2
  84. #define        STR_OUT_OF_MEMORY        3
  85. #define        STR_APP_NO_AE            4
  86. #define        STR_APP_NOT_FOUND        5
  87.  
  88. #define        APPLE_MENU_ID            1000        /* MENU resource IDs */
  89. #define        FILE_MENU_ID            1001
  90. #define        EDIT_MENU_ID            1002
  91. #define        OTHER_MENU_ID            1003
  92.  
  93. #define        APPLE_ABOUT                1            /* Apple menu items */
  94.  
  95. #define        FILE_NEW_MONITOR        1            /* File menu items */
  96. #define        FILE_CLOSE_WINDOW        2
  97. #define        FILE_LAUNCH                4
  98. #define        FILE_QUIT                6
  99.  
  100. #define        EDIT_UNDO                1            /* Edit menu items */
  101. #define        EDIT_CUT                3
  102. #define        EDIT_COPY                4
  103. #define        EDIT_PASTE                5
  104. #define        EDIT_CLEAR                6
  105. #define        EDIT_SELECTALL            8
  106.  
  107. #define        OTHER_PREFERENCES        1            /* Other menu items */
  108. #define        OTHER_BRING_TO_FRONT    3
  109. #define        OTHER_PROCESS_INFO        4
  110. #define        OTHER_UPDATE            5
  111. #define        OTHER_QUIT                6
  112.  
  113. #define        MAIN_LIST_BOX            2            /* MAIN_DLOG_ID item IDs */
  114. #define        MAIN_TITLE                1
  115.  
  116. #define        LISTBOX_TEXT_FONT        monaco        /* Font info for monitor window */
  117. #define        LISTBOX_TEXT_SIZE        9
  118. #define        LISTBOX_TITLE_FONT        monaco
  119. #define        LISTBOX_TITLE_SIZE        9
  120. #define        LISTBOX_TITLE_STYLE        bold
  121. #define        LISTBOX_SORTED_STYLE    bold | underline
  122.  
  123. #define        TICKS_PER_SECOND        60                            /* Defined by Macintosh */
  124. #define        REFRESH_MONITOR_TICKS    (5.0 * TICKS_PER_SECOND)    /* Default, 5 seconds */
  125. #define        MIN_REFRESH_RATE        (0.1 * TICKS_PER_SECOND)    /* 1/10th second */
  126. #define        MAX_REFRESH_RATE        (10.0 * TICKS_PER_SECOND)    /* 10 seconds */
  127.  
  128. #define        PREF_RES_TYPE            'PREF'        /* PREFerence resources */
  129. #define        DEF_WIND_POS_ID            1000        /* Default window position */
  130. #define        REFRESH_RATE_ID            1001        /* Refresh rate preference */
  131. #define        OPEN_DEF_WIND_ID        1002        /* Open default window on startup? */
  132. #define        AUTO_UPDATE_ID            1003        /* Update window automatically? */
  133. #define        HIDE_IN_BACKGROUND        1004        /* Hide window in background? */
  134. #define        DEF_WIND_VERTICAL        1005        /* Default vertical window size */
  135. #define        DEF_SAVE_PREFS            1006        /* Save preference items? */
  136.  
  137. #define        MAX_PROCESSES            100            /* Max processes program can handle */
  138. #define        SCROLLBAR_WIDTH            16
  139.  
  140. /********************************************************************************/
  141.  
  142. /* Global variables */
  143.  
  144. Rect        gGrowRect, gZoomRect;        /* Limits: growing, zooming */
  145. int            gInBackground;                /* Is application currently running in background? */
  146. int            gDone;                        /* Has user chosen Quit from the menu? */
  147.  
  148. int            gHasGestalt;                /* Is Gestalt available? */
  149. long        gHasAppleEvents;            /* Are Apple Events available? */
  150. long        gHasStandardFile;            /* Has new standard file manager calls */
  151.  
  152. MenuHandle    gAppleMenu, gFileMenu, gEditMenu, gOtherMenu;    /* Menus */
  153. WindowPtr    gMonitorWindow;                /* The monitor window! */
  154. ListBoxPtr    gMonitorLB;                    /* Listbox for monitor window */
  155. Point        gMonitorWindPt;                /* Default monitor window position */
  156. int            gWindowHeight;                /* Window vertical size default */
  157. int            gRefreshRate;                /* Number of ticks before refresh */
  158. int            gOpenDefWindow;                /* Open window on startup? */
  159. int            gAutoUpdate;                /* Update automatically? */
  160. int            gHideInBackground;            /* Hide window in background? */
  161. int            gSavePrefs;                    /* Restore window size/position? */
  162.  
  163. ProcessSerialNumber        *PSNs;            /* List of PSNs */
  164.  
  165. /********************************************************************************/
  166.  
  167. /* Prototypes */
  168.  
  169. void        InitProgram(void);
  170. void        DoEvents(void);
  171. void        Cleanup(void);
  172. void        HandleSetupMenus(EventRecord *theEvent);
  173. void        HandleMenuCommand(long theCommand);
  174. void        HandleInContent(WindowPtr theWindow, EventRecord *theEvent);
  175. void        HandleCloseWindow(WindowPtr theWindow);
  176. void        HandleUpdateWindow(WindowPtr theWindow);
  177. void        HandleActivateWindow(WindowPtr theWindow, int activate);
  178. void        HandleSuspendResume(int resume);
  179. void        HandleInZoomBox(WindowPtr theWindow, EventRecord *theEvent, int windowPart);
  180. void        HandleHighLevelEvent(EventRecord *theEvent);
  181. void        HandleNullEvent(void);
  182. void            HandleSendAEQuit(ProcessSerialNumber *thePSN);
  183. pascal OSErr    HandleAEOpenApp(AppleEvent *theAE, AppleEvent *replyAE, long refCon);
  184. pascal OSErr    HandleAEQuit(AppleEvent *theAE, AppleEvent *replyAE, long refCon);
  185. void            HandleOpenMonitor(void);
  186. void        HandleLaunchApp(void);
  187. void        HandleAboutDialog(void);
  188. void        HandlePreferencesDialog(void);
  189. void        HandleProcessInfoDialog(ProcessSerialNumber *thePSN);
  190. OSErr        MyGotRequiredParams(AppleEvent *theAE);
  191. void        ResizeMonitorWindow(int height, int width);
  192. void        CalcMonitorWindow(void);
  193. void        DoAlert(int alertType, int stringID, char *text);
  194.  
  195. pascal Boolean    GenericDialogFilter(DialogPtr theDialog, EventRecord *theEvent,
  196.                                     int *theItem);
  197.  
  198. /********************************************************************************/
  199. /*                                                                                */
  200. /* Begin the program.                                                            */
  201. /*                                                                                */
  202. /********************************************************************************/
  203.  
  204. main()
  205.  
  206.     {
  207.     InitToolbox();            /* Standard Macintosh toolbox inits */
  208.     
  209.     gDone = FALSE;            /* Do program until gDone == TRUE */
  210.     InitProgram();
  211.     
  212.     if (!gDone)                /* Was the init good? */
  213.         DoEvents();            /* Handle events/do the program */
  214.         
  215.     Cleanup();                /* Clean up variables and memory, etc. */
  216.     }
  217.     
  218. /********************************************************************************/
  219. /*                                                                                */
  220. /* This routine initializes any variables needed by the program; generally        */
  221. /* these are global variables, allocating memory for whatever uses, etc.  This    */
  222. /* code sets up the program and is needed before an AE of OpenApp occurs.        */
  223. /*                                                                                */
  224. /********************************************************************************/
  225.  
  226. void InitProgram(void)
  227.  
  228.     {
  229.     int            i;
  230.     
  231.     for (i=0; i<10; i++)    /* Increase the size of the heap a little */
  232.         MaxApplZone();
  233.         
  234.     InitResHelper();        /* Initialize my libraries */
  235.     InitListBox_LB();
  236.     InitMiscLib();
  237.     InitDialogLib();
  238.     
  239.     /* We want Gestalt to continue (we're being snotty!  Well, this is a */
  240.     /* System 7 app!  I declare it so!) */
  241.     
  242.     if (!TrapAvailable(_Gestalt))
  243.         {
  244.         DoAlert(STOP_ALERT, STR_SYSTEM7_REQUIRED, "");
  245.         gDone = TRUE;
  246.         }
  247.     else    /* Do we have all the Toolbox Managers/thing-a-ma-bobs before continuing? */
  248.         {
  249.         if ((Gestalt(gestaltAppleEventsAttr, &gHasAppleEvents) != noErr) ||
  250.             (Gestalt(gestaltStandardFileAttr, &gHasStandardFile) != noErr))
  251.                 {
  252.                 DoAlert(STOP_ALERT, STR_SYSTEM7_REQUIRED, "");
  253.                 gDone = TRUE;
  254.                 }
  255.                 
  256.         /* All this is documented in Inside Macintosh VI. */
  257.         gHasAppleEvents = BitTst(&gHasAppleEvents, 31-gestaltAppleEventsPresent);
  258.         gHasStandardFile = BitTst(&gHasStandardFile, 31-gestaltStandardFile58);
  259.         
  260.         if (!gHasAppleEvents || !gHasStandardFile)
  261.             {
  262.             DoAlert(STOP_ALERT, STR_SYSTEM7_REQUIRED, "");
  263.             gDone = TRUE;
  264.             }
  265.         }
  266.         
  267.     gAppleMenu = GetMenu(APPLE_MENU_ID);    /* Set up the menu bar */
  268.     gFileMenu = GetMenu(FILE_MENU_ID);
  269.     gEditMenu = GetMenu(EDIT_MENU_ID);
  270.     gOtherMenu = GetMenu(OTHER_MENU_ID);
  271.     
  272.     if ((gAppleMenu == NULL) ||                /* Make sure the menu resources exist */
  273.         (gFileMenu == NULL) ||
  274.         (gEditMenu == NULL) ||
  275.         (gOtherMenu == NULL))
  276.             {
  277.             DoAlert(STOP_ALERT, STR_CANT_GET_RESOURCES, "");
  278.             gDone = TRUE;
  279.             }
  280.             
  281.     /* Allocate memory for the PSN array */
  282.     PSNs = (ProcessSerialNumber *)malloc(sizeof(ProcessSerialNumber) * MAX_PROCESSES);
  283.     if (PSNs == NULL)
  284.         {
  285.         DoAlert(STOP_ALERT, STR_OUT_OF_MEMORY, "");
  286.         gDone = TRUE;
  287.         }
  288.         
  289.     if (gDone)        /* If we don't have what we need so far, return now */
  290.         return;
  291.         
  292.     InsertMenu(gAppleMenu, 0);                        /* Add menus to the menu bar */
  293.     InsertMenu(gFileMenu, 0);
  294.     InsertMenu(gEditMenu, 0);
  295.     InsertMenu(gOtherMenu, 0);
  296.  
  297.     AddResMenu(gAppleMenu, 'DRVR');                    /* Add DAs to Apple menu */
  298.     DrawMenuBar();
  299.     
  300.     gInBackground = FALSE;                            /* We start in the foreground */
  301.     
  302.     if (gHasAppleEvents)            /* Support OpenApp & Quit AppleEvents */
  303.         {
  304.         AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
  305.                               (EventHandlerProcPtr)HandleAEOpenApp, (long)0, FALSE);
  306.         AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  307.                               (EventHandlerProcPtr)HandleAEQuit, (long)0, FALSE);
  308.         }
  309.         
  310.     /* Read in preferences (resources) */
  311.     {
  312.     Point        defPt = {0, 0};
  313.     int            zero = 0;
  314.     int            defRR = REFRESH_MONITOR_TICKS;
  315.     int            false = FALSE, true = TRUE;
  316.     
  317.     GetRes(PREF_RES_TYPE, DEF_WIND_POS_ID, "Window Position", sizeof(Point),
  318.            &gMonitorWindPt, &defPt);
  319.     GetRes(PREF_RES_TYPE, REFRESH_RATE_ID, "Refresh Rate", sizeof(int),
  320.            &gRefreshRate, &defRR);
  321.     GetRes(PREF_RES_TYPE, OPEN_DEF_WIND_ID, "Open Default Window", sizeof(int),
  322.            &gOpenDefWindow, &false);
  323.     GetRes(PREF_RES_TYPE, AUTO_UPDATE_ID, "Auto Update", sizeof(int),
  324.            &gAutoUpdate, &true);
  325.     GetRes(PREF_RES_TYPE, HIDE_IN_BACKGROUND, "Hide In Background", sizeof(int),
  326.            &gHideInBackground, &false);
  327.     GetRes(PREF_RES_TYPE, DEF_WIND_VERTICAL, "Window Height", sizeof(int),
  328.            &gWindowHeight, &zero);
  329.     GetRes(PREF_RES_TYPE, DEF_SAVE_PREFS, "Save Window Size/Pos", sizeof(int),
  330.            &gSavePrefs, &true);
  331.     }
  332.     
  333.     gMonitorLB = NULL;            /* Initialize our global variables */
  334.     gMonitorWindow = NULL;
  335.     }
  336.     
  337. /********************************************************************************/
  338. /*                                                                                */
  339. /* This routine handles the main event loop and distributes events to other        */
  340. /* routines.                                                                    */
  341. /*                                                                                */
  342. /********************************************************************************/
  343.  
  344. void DoEvents(void)
  345.  
  346.     {
  347.     EventRecord        theEvent;
  348.     int                windowPart;
  349.     WindowPtr        whichWindow;
  350.     long            newSize;
  351.     
  352.     while (!gDone)
  353.         {
  354.         /* Get NULL event every 60 ticks (1 second) */
  355.         WaitNextEvent(everyEvent, &theEvent, 60L, NULL);
  356.         
  357.         switch (theEvent.what)        /* Do the event */
  358.             {
  359.             case mouseUp:
  360.                 IsDblClick(&theEvent);        /* Set things up for double clicks */
  361.                 break;
  362.                 
  363.             case mouseDown:
  364.                 windowPart = FindWindow(theEvent.where, &whichWindow);
  365.                 switch (windowPart)
  366.                     {
  367.                     case inMenuBar:
  368.                         HandleSetupMenus(&theEvent);
  369.                         HandleMenuCommand(MenuSelect(theEvent.where));
  370.                         break;
  371.                         
  372.                     case inSysWindow:
  373.                         SystemClick(&theEvent, whichWindow);
  374.                         break;
  375.                         
  376.                     case inContent:
  377.                         if (whichWindow != FrontWindow())
  378.                             SelectWindow(whichWindow);
  379.                         else
  380.                             HandleInContent(whichWindow, &theEvent);
  381.                         break;
  382.                         
  383.                     case inDrag:
  384.                         DragWindow(whichWindow, theEvent.where, &globalDragRect);
  385.                         
  386.                         /* Save the window position */
  387.                         if (whichWindow == gMonitorWindow)
  388.                             {
  389.                             GrafPtr        oldPort;
  390.                             
  391.                             GetPort(&oldPort);
  392.                             SetPort(whichWindow);
  393.                             SetPt(&gMonitorWindPt, 0, 0);
  394.                             LocalToGlobal(&gMonitorWindPt);
  395.                             SetPort(oldPort);
  396.                             WriteRes(&gMonitorWindPt);
  397.                             }
  398.                         break;
  399.                         
  400.                     case inGrow:
  401.                         newSize = GrowWindow(whichWindow, theEvent.where, &gGrowRect);
  402.                         if (newSize != (long)0)
  403.                             ResizeMonitorWindow(HiWord(newSize), LoWord(newSize));
  404.                         break;
  405.                         
  406.                     case inGoAway:
  407.                         if (TrackGoAway(whichWindow, theEvent.where))
  408.                             HandleCloseWindow(whichWindow);
  409.                         break;
  410.                         
  411.                     case inZoomIn:
  412.                         HandleInZoomBox(whichWindow, &theEvent, inZoomIn);
  413.                         break;
  414.                         
  415.                     case inZoomOut:
  416.                         HandleInZoomBox(whichWindow, &theEvent, inZoomOut);
  417.                     }
  418.                 break;
  419.                 
  420.             case keyDown:
  421.                 HandleSetupMenus(&theEvent);
  422.                 HandleMenuCommand(MenuKey((char)(theEvent.message & charCodeMask)));
  423.                 break;
  424.                 
  425.             case updateEvt:
  426.                 HandleUpdateWindow((WindowPtr)theEvent.message);
  427.                 break;
  428.                 
  429.             case activateEvt:
  430.                 HandleActivateWindow((WindowPtr)theEvent.message,
  431.                                      (int)(theEvent.modifiers & activeFlag));
  432.                 break;
  433.                 
  434.             case osEvt:
  435.                 /* What particular kind of OS event is this */
  436.                 switch ((theEvent.message & 0xFF000000) >> 24)
  437.                     {
  438.                     case suspendResumeMessage:
  439.                         HandleSuspendResume((int)(theEvent.message & resumeFlag));
  440.                         break;
  441.                         
  442.                     case mouseMovedMessage:
  443.                         break;
  444.                     }
  445.                 break;
  446.                 
  447.             case kHighLevelEvent:
  448.                 HandleHighLevelEvent(&theEvent);
  449.                 break;
  450.                 
  451.             case nullEvent:
  452.                 HandleNullEvent();
  453.                 break;
  454.             }
  455.         }
  456.     }
  457.     
  458. /********************************************************************************/
  459. /*                                                                                */
  460. /* This routine cleans up memory, frees up used memory, etc. and sets gDone to    */
  461. /* TRUE so the program will quit on next event loop.                            */
  462. /*                                                                                */
  463. /********************************************************************************/
  464.  
  465. void Cleanup(void)
  466.  
  467.     {
  468.     if (gMonitorWindow != NULL)
  469.         {
  470.         /* Clean up things associated with the window */
  471.         DisposeListBox_LB(gMonitorLB);
  472.         DisposeWindow(gMonitorWindow);
  473.         gMonitorLB = NULL;
  474.         gMonitorWindow = NULL;
  475.         }
  476.         
  477.     /* Remove the menus from the menu list */
  478.     DeleteMenu(APPLE_MENU_ID);
  479.     DeleteMenu(FILE_MENU_ID);
  480.     DeleteMenu(EDIT_MENU_ID);
  481.     DeleteMenu(OTHER_MENU_ID);
  482.     
  483.     /* Free up the menu memory */
  484.     DisposeMenu(gAppleMenu);
  485.     DisposeMenu(gFileMenu);
  486.     DisposeMenu(gEditMenu);
  487.     DisposeMenu(gOtherMenu);
  488.     
  489.     /* Remove Apple Events from the Apple Event Manager dispatch table */
  490.     if (gHasAppleEvents)
  491.         {
  492.         AERemoveEventHandler(kCoreEventClass, kAEOpenApplication,
  493.                              (EventHandlerProcPtr)HandleAEOpenApp, FALSE);
  494.         AERemoveEventHandler(kCoreEventClass, kAEQuitApplication,
  495.                              (EventHandlerProcPtr)HandleAEQuit, FALSE);
  496.         }
  497.         
  498.     free(PSNs);        /* Free up this array */
  499.     gDone = TRUE;
  500.     }
  501.     
  502. /********************************************************************************/
  503. /*                                                                                */
  504. /* Use this routine to dim, highlight, checkmark, etc. the menus depending on    */
  505. /* the current state of the program.                                            */
  506. /*                                                                                */
  507. /********************************************************************************/
  508.  
  509. void HandleSetupMenus(EventRecord *theEvent)
  510.  
  511.     {
  512.     /* I know the Edit menu is always dim, but things loog good here. */
  513.     DisableItem(gEditMenu, EDIT_UNDO);
  514.     DisableItem(gEditMenu, EDIT_CUT);
  515.     DisableItem(gEditMenu, EDIT_PASTE);
  516.     DisableItem(gEditMenu, EDIT_CLEAR);
  517.     DisableItem(gEditMenu, EDIT_SELECTALL);
  518.     
  519.     if (gMonitorWindow == NULL)
  520.         {
  521.         EnableItem(gFileMenu, FILE_NEW_MONITOR);
  522.         DisableItem(gFileMenu, FILE_CLOSE_WINDOW);
  523.         DisableItem(gEditMenu, EDIT_COPY);
  524.         DisableItem(gOtherMenu, OTHER_BRING_TO_FRONT);
  525.         DisableItem(gOtherMenu, OTHER_PROCESS_INFO);
  526.         DisableItem(gOtherMenu, OTHER_UPDATE);
  527.         DisableItem(gOtherMenu, OTHER_QUIT);
  528.         }
  529.     else    /* The monitor window is open */
  530.         {
  531.         DisableItem(gFileMenu, FILE_NEW_MONITOR);
  532.         EnableItem(gFileMenu, FILE_CLOSE_WINDOW);
  533.         EnableItem(gOtherMenu, OTHER_UPDATE);
  534.         
  535.         /* Is anything selected? */
  536.         if (GetSelected_LB(gMonitorLB) != LB_NoneSelected)
  537.             {
  538.             EnableItem(gEditMenu, EDIT_COPY);
  539.             EnableItem(gOtherMenu, OTHER_BRING_TO_FRONT);
  540.             EnableItem(gOtherMenu, OTHER_PROCESS_INFO);
  541.             EnableItem(gOtherMenu, OTHER_QUIT);
  542.             }
  543.         else
  544.             {
  545.             DisableItem(gEditMenu, EDIT_COPY);
  546.             DisableItem(gOtherMenu, OTHER_BRING_TO_FRONT);
  547.             DisableItem(gOtherMenu, OTHER_PROCESS_INFO);
  548.             DisableItem(gOtherMenu, OTHER_QUIT);
  549.             }
  550.         }
  551.     }
  552.     
  553. /********************************************************************************/
  554. /*                                                                                */
  555. /* Use this routine to parse out which menu item was chosen and then dispatch    */
  556. /* the command.                                                                    */
  557. /*                                                                                */
  558. /********************************************************************************/
  559.  
  560. void HandleMenuCommand(long theCommand)
  561.  
  562.     {
  563.     int            menuID, menuItem, accNumber;
  564.     Str255        accName;
  565.     GrafPtr        oldPort;
  566.     char        tempStr[256];
  567.     
  568.     menuID = HiWord(theCommand);
  569.     menuItem = LoWord(theCommand);
  570.     
  571.     switch (menuID)
  572.         {
  573.         case APPLE_MENU_ID:
  574.             switch (menuItem)
  575.                 {
  576.                 case APPLE_ABOUT:
  577.                     HandleAboutDialog();
  578.                     break;
  579.                     
  580.                 default:    /* DAs */
  581.                     GetItem(gAppleMenu, menuItem, accName);
  582.                     accNumber = OpenDeskAcc(accName);
  583.                     break;
  584.                 }
  585.             break;
  586.             
  587.         case EDIT_MENU_ID:
  588.             switch (menuItem)
  589.                 {
  590.                 /* Support Copy by getting the text of the selected item */
  591.                 case EDIT_COPY:
  592.                     strcpy(tempStr, GetRowText_LB(gMonitorLB, GetSelected_LB(gMonitorLB)));
  593.                     ZeroScrap();
  594.                     PutScrap((long)strlen(tempStr), 'TEXT', tempStr);
  595.                     break;
  596.                 }
  597.             break;
  598.             
  599.         case FILE_MENU_ID:
  600.             switch (menuItem)
  601.                 {
  602.                 case FILE_NEW_MONITOR:
  603.                     HandleOpenMonitor();
  604.                     break;
  605.                     
  606.                 case FILE_CLOSE_WINDOW:
  607.                     HandleCloseWindow(FrontWindow());
  608.                     break;
  609.                     
  610.                 case FILE_LAUNCH:
  611.                     HandleLaunchApp();
  612.                     break;
  613.                     
  614.                 case FILE_QUIT:
  615.                     Cleanup();
  616.                     break;
  617.                 }
  618.             break;
  619.             
  620.         case OTHER_MENU_ID:
  621.             switch (menuItem)
  622.                 {
  623.                 case OTHER_PREFERENCES:
  624.                     HandlePreferencesDialog();
  625.                     break;
  626.                     
  627.                 case OTHER_BRING_TO_FRONT:
  628.                     SetFrontProcess(&PSNs[GetSelected_LB(gMonitorLB)]);
  629.                     break;
  630.                     
  631.                 case OTHER_PROCESS_INFO:
  632.                     HandleProcessInfoDialog(&PSNs[GetSelected_LB(gMonitorLB)]);
  633.                     break;
  634.                     
  635.                 case OTHER_UPDATE:
  636.                     CalcMonitorWindow();
  637.                     DrawListBox_LB(gMonitorLB);
  638.                     break;
  639.                     
  640.                 case OTHER_QUIT:
  641.                     HandleSendAEQuit(&PSNs[GetSelected_LB(gMonitorLB)]);
  642.                     break;
  643.                 }
  644.             break;
  645.         }
  646.         
  647.     HiliteMenu(0);    /* Turn off the menu highlighting the Mac did */
  648.     }
  649.     
  650. /********************************************************************************/
  651. /*                                                                                */
  652. /* When a click occurs inside a window, this routine gets called.  You will        */
  653. /* need to see what item got clicked on!                                        */
  654. /*                                                                                */
  655. /********************************************************************************/
  656.  
  657. void HandleInContent(WindowPtr theWindow, EventRecord *theEvent)
  658.  
  659.     {
  660.     ListBoxPtr        whichListBox;
  661.     
  662.     /* Is is our window?  Was the click in the listbox?  Was it a double-click? */
  663.     if ((theWindow == gMonitorWindow) &&
  664.         (PtInListBox_LB(gMonitorWindow, theEvent->where, &whichListBox)))
  665.             if (TrackListBox_LB(whichListBox, theEvent->where, theEvent->modifiers) &&
  666.                 (IsDblClick(theEvent)))
  667.                     SetFrontProcess(&PSNs[GetSelected_LB(gMonitorLB)]);
  668.                     
  669. #ifdef TEST
  670.             if (IsDblClick(theEvent))
  671.                 SetFrontProcess(&PSNs[GetSelected_LB(gMonitorLB)]);
  672.             else    /* Track the mouse in the listbox */
  673.                 TrackListBox_LB(whichListBox, theEvent->where, theEvent->modifiers);
  674. #endif
  675.     }
  676.     
  677. /********************************************************************************/
  678. /*                                                                                */
  679. /* Use this routine to handle things when a window is closed (either by the        */
  680. /* menu or by the close box).  The window being closed is theWindow.            */
  681. /*                                                                                */
  682. /********************************************************************************/
  683.  
  684. void HandleCloseWindow(WindowPtr theWindow)
  685.  
  686.     {
  687.     if (theWindow == gMonitorWindow)
  688.         {
  689.         DisposeListBox_LB(gMonitorLB);
  690.         gMonitorLB = NULL;
  691.         
  692.         DisposeWindow(gMonitorWindow);
  693.         gMonitorWindow = NULL;
  694.         }
  695.     }
  696.     
  697. /********************************************************************************/
  698. /*                                                                                */
  699. /* Do your window updating in this routine.  The window that needs to be        */
  700. /* updated is theWindow.                                                        */
  701. /*                                                                                */
  702. /********************************************************************************/
  703.  
  704. void HandleUpdateWindow(WindowPtr theWindow)
  705.  
  706.     {
  707.     GrafPtr        oldPort;
  708.     
  709.     GetPort(&oldPort);
  710.     SetPort(theWindow);
  711.     BeginUpdate(theWindow);
  712.     
  713.     /* Draw contents for theWindow here */
  714.     if (theWindow == gMonitorWindow)
  715.         {
  716.         DrawListBox_LB(gMonitorLB);
  717.         DrawGrowBoxOnly(gMonitorWindow);
  718.         }
  719.         
  720.     EndUpdate(theWindow);
  721.     SetPort(oldPort);
  722.     }
  723.     
  724. /********************************************************************************/
  725. /*                                                                                */
  726. /* Hilite/dehilight the window here.                                            */
  727. /*                                                                                */
  728. /********************************************************************************/
  729.  
  730. void HandleActivateWindow(WindowPtr theWindow, int activate)
  731.  
  732.     {
  733.     if (theWindow == NULL)
  734.         return;
  735.         
  736.     if (activate)    /* Is theWindow coming to the foreground? */
  737.         {
  738.         if (theWindow == gMonitorWindow)
  739.             ListBoxState_LB(gMonitorLB, LB_Activate);
  740.             
  741.         InitCursor();        /* Just in case another app sets it to something else */
  742.         }
  743.     else    /* We're deactivating theWindow */
  744.         {
  745.         if (theWindow == gMonitorWindow)
  746.             ListBoxState_LB(gMonitorLB, LB_Deactivate);
  747.         }
  748.     }
  749.     
  750. /********************************************************************************/
  751. /*                                                                                */
  752. /* Handle suspend and resume events here.  We need to handle activate events    */
  753. /* ourself if we are being suspended or resuming.                                */
  754. /*                                                                                */
  755. /********************************************************************************/
  756.  
  757. void HandleSuspendResume(int resume)
  758.  
  759.     {
  760.     if (resume)        /* Is our app coming to the foreground? */
  761.         {
  762.         if (gMonitorWindow != NULL)
  763.             if (gHideInBackground)
  764.                 ShowWindow(gMonitorWindow);
  765.             else
  766.                 HandleActivateWindow(gMonitorWindow, TRUE);
  767.                 
  768.         gInBackground = FALSE;
  769.         }
  770.     else    /* We are being suspended, our app is going to the background */
  771.         {
  772.         if (gMonitorWindow != NULL)
  773.             if (gHideInBackground)
  774.                 HideWindow(gMonitorWindow);
  775.             else
  776.                 HandleActivateWindow(gMonitorWindow, FALSE);
  777.                 
  778.         gInBackground = TRUE;
  779.         }
  780.     }
  781.     
  782. /********************************************************************************/
  783. /*                                                                                */
  784. /* This routine will handle things when the user clicks on the zoom box.        */
  785. /*                                                                                */
  786. /********************************************************************************/
  787.  
  788. void HandleInZoomBox(WindowPtr theWindow, EventRecord *theEvent, int windowPart)
  789.  
  790.     {
  791.     long            centerLat, centerLong;
  792.     GrafPtr            oldPort;
  793.     Rect            sbRect;
  794.     FontInfo        auxWindFont;
  795.     
  796.     GetPort(&oldPort);
  797.     SetPort(theWindow);
  798.     
  799.     if (TrackBox(theWindow, theEvent->where, windowPart))
  800.         {
  801.         EraseRect(&theWindow->portRect);            /* ZoomWindow() says to do this */
  802.         ZoomWindow(theWindow, windowPart, FALSE);    /* Zoom in or out (depending on windowpart) */
  803.         }
  804.         
  805.     SetPort(oldPort);
  806.     }
  807.     
  808. /********************************************************************************/
  809. /*                                                                                */
  810. /* This routine calls to the Apple Event Manager to handle Apple Events.        */
  811. /*                                                                                */
  812. /********************************************************************************/
  813.  
  814. void HandleHighLevelEvent(EventRecord *theEvent)
  815.  
  816.     {
  817.     OSErr        err;
  818.     
  819.     err = AEProcessAppleEvent(theEvent);    /* Dispatch the Apple Event */
  820.     }
  821.     
  822. /********************************************************************************/
  823. /*                                                                                */
  824. /* Do background tasks here.  Remember to set the 'SIZE' resource bits properly    */
  825. /* so you will get NULL events if you want them!                                */
  826. /*                                                                                */
  827. /********************************************************************************/
  828.  
  829. void HandleNullEvent(void)
  830.  
  831.     {
  832.     static long        currTicks = 0;
  833.     long            newTicks;
  834.     
  835.     if (currTicks == 0)                /* This will only happen on first NULL event */
  836.         currTicks = TickCount();
  837.         
  838.     /* Here we check to see if a period of time has gone by, if so, update */
  839.     /* the window if it is open. */
  840.     
  841.     if (gMonitorLB != NULL)
  842.         {
  843.         newTicks = currTicks + (long)gRefreshRate;
  844.         if (newTicks < TickCount())
  845.             {
  846.             if (gAutoUpdate)        /* Is pref set to update automatically? */
  847.                 {
  848.                 CalcMonitorWindow();
  849.                 DrawListBox_LB(gMonitorLB);
  850.                 }
  851.                 
  852.             currTicks = TickCount();
  853.             }
  854.         }
  855.     }
  856.     
  857. /********************************************************************************/
  858. /*                                                                                */
  859. /* This routine handles the "Open Application" Apple Event.                        */
  860. /*                                                                                */
  861. /********************************************************************************/
  862.  
  863. pascal OSErr HandleAEOpenApp(AppleEvent *theAE, AppleEvent *replyAE, long refCon)
  864.  
  865.     {
  866.     OSErr        err;
  867.     
  868.     err = MyGotRequiredParams(theAE);        /* All parameters gotten? */
  869.     
  870.     if (err == noErr)                        /* If no errors, perform program "opening" */
  871.         {
  872.         if (gOpenDefWindow)                    /* Do we need to start with an open window? */
  873.             HandleOpenMonitor();
  874.         }
  875.         
  876.     return(err);
  877.     }
  878.     
  879. /********************************************************************************/
  880. /*                                                                                */
  881. /* This routine handles the "Quit Application" Apple Event.                        */
  882. /*                                                                                */
  883. /********************************************************************************/
  884.  
  885. pascal OSErr HandleAEQuit(AppleEvent *theAE, AppleEvent *replyAE, long refCon)
  886.  
  887.     {
  888.     OSErr        err;
  889.     
  890.     err = MyGotRequiredParams(theAE);        /* All parameters gotten? */
  891.     
  892.     if (err == noErr)                        /* If no errors, quit program */
  893.         Cleanup();                            /* Clean up variables and memory, etc. */
  894.         
  895.     return(err);
  896.     }
  897.     
  898. /********************************************************************************/
  899. /*                                                                                */
  900. /* This routine will send a high level Apple Event to the specified application    */
  901. /* ONLY if the application is high level event aware.                            */
  902. /*                                                                                */
  903. /* Input:    thePSN    = The process serial number of the app to send the AE to.    */
  904. /*                                                                                */
  905. /* Note:    This is my first attempt at Apple Events, so the code probably        */
  906. /*            doesn't look too good.                                                */
  907. /*                                                                                */
  908. /********************************************************************************/
  909.  
  910. void HandleSendAEQuit(ProcessSerialNumber *thePSN)
  911.  
  912.     {
  913.     ProcessInfoRec    theProcInfo;
  914.     Str255            procName, otherName;
  915.     FSSpec            locationName;
  916.     char            tempStr[256];
  917.     OSErr            err;
  918.     AEAddressDesc    targetAddress;
  919.     AppleEvent        theAE, replyAE;
  920.     Handle            psnHandle;
  921.     
  922.     /* Prepare and then get the process information */
  923.     theProcInfo.processInfoLength = sizeof(ProcessInfoRec);
  924.     theProcInfo.processName = procName;
  925.     theProcInfo.processAppSpec = &locationName;
  926.     
  927.     err = GetProcessInformation(thePSN, &theProcInfo);
  928.     if (err == noErr)
  929.         {
  930.         if (theProcInfo.processMode & modeHighLevelEventAware)
  931.             {
  932.             /* Set up the targetAddress (thePSN info for the Apple Event Manger) */
  933.             psnHandle = NewHandle((Size)sizeof(ProcessSerialNumber));
  934.             *((ProcessSerialNumber *)*psnHandle) = *thePSN;
  935.             targetAddress.descriptorType = typeProcessSerialNumber;    /* We are using PSN */
  936.             targetAddress.dataHandle = psnHandle;
  937.             
  938.             /* Create the Apple Event "Quit" */
  939.             err = AECreateAppleEvent('aevt',
  940.                                      'quit',
  941.                                      &targetAddress,
  942.                                      kAutoGenerateReturnID,
  943.                                      kAnyTransactionID,
  944.                                      &theAE);
  945.                                      
  946.             /* Send the Apple Event */
  947.             AESend(&theAE,
  948.                    &replyAE,
  949.                    kAENoReply + kAENeverInteract + kAECanSwitchLayer,
  950.                    kAENormalPriority,
  951.                    kAEDefaultTimeout,
  952.                    NULL,
  953.                    NULL);
  954.             }
  955.         else
  956.             DoAlert(NOTE_ALERT, STR_APP_NO_AE, "");        /* App not AE aware */
  957.         }
  958.     else
  959.         DoAlert(NOTE_ALERT, STR_APP_NOT_FOUND, "");        /* App not found anymore */
  960.     }
  961.     
  962. /********************************************************************************/
  963. /*                                                                                */
  964. /* This routine will open up and create structures for the monitor process        */
  965. /* window.                                                                        */
  966. /*                                                                                */
  967. /********************************************************************************/
  968.  
  969. void HandleOpenMonitor(void)
  970.  
  971.     {
  972.     Rect        tempRect;
  973.     int            titleWidth;
  974.     
  975.     gMonitorWindow = GetNewWindow(MONITOR_WIND_ID, NULL, (WindowPtr)-1);
  976.     if (gMonitorWindow == NULL)
  977.         {
  978.         DisplayAlert(BAD_RESOURCES, STOP_ALERT, NULL);
  979.         return;
  980.         }
  981.         
  982.     /* Set the window size to that of the prefs if the user wants to */
  983.     if (gSavePrefs && (gWindowHeight != 0))
  984.         SizeWindow(gMonitorWindow,
  985.                    gMonitorWindow->portRect.right - gMonitorWindow->portRect.left,
  986.                    gWindowHeight,
  987.                    FALSE);
  988.                    
  989.     /* Create the listbox rect */
  990.     SetRect(&tempRect,
  991.             gMonitorWindow->portRect.left - 1,
  992.             gMonitorWindow->portRect.top - 1,
  993.             gMonitorWindow->portRect.right + 1,
  994.             gMonitorWindow->portRect.bottom + 1);
  995.             
  996.     /* Create the list box */
  997.     gMonitorLB = NewListBox_LB(gMonitorWindow, &tempRect, FALSE, NULL, NULL);
  998.     ListBoxState_LB(gMonitorLB, LB_GrowBoxOn);
  999.     
  1000.     TextFont_LB(gMonitorLB, LISTBOX_TEXT_FONT);
  1001.     TextSize_LB(gMonitorLB, LISTBOX_TEXT_SIZE);
  1002.     
  1003.     /* Set up the title for the listbox */
  1004.     TitleFont_LB(gMonitorLB, LISTBOX_TITLE_FONT);
  1005.     TitleSize_LB(gMonitorLB, LISTBOX_TITLE_SIZE);
  1006.     TitleStyle_LB(gMonitorLB, LISTBOX_TITLE_STYLE, LISTBOX_SORTED_STYLE);
  1007.     
  1008.     /* Note: This title must match the data inserted into the listbox for field widths! */
  1009.     SetTitleText_LB(gMonitorLB, "Process Name         ]Type ]Sign ]Location  ]Size  ]Free ", 0L);
  1010.     ListBoxState_LB(gMonitorLB, LB_TitleOn);
  1011.     
  1012.     /* Here, we resize the listbox to the width of the listbox title.  Then we */
  1013.     /* size the window to the size of the listbox.  This frees us from having to */
  1014.     /* have the resources exactly match the items we need.  The user is free to */
  1015.     /* modify the WIND resource vertically, but we will override any horizontal */
  1016.     /* changes.  We need this code here instead of calling ResizeMonitorWindow() */
  1017.     /* so we can initially set up the listbox size. */
  1018.     
  1019.     GetFieldInfo_LB(gMonitorLB, 0, &titleWidth, NULL, NULL, NULL);
  1020.     GetRect_LB(gMonitorLB, &tempRect);
  1021.     tempRect.right = tempRect.left +
  1022.                      titleWidth +
  1023.                      SCROLLBAR_WIDTH +
  1024.                      GetLeftMargin_LB(gMonitorLB)+1;    /* +1 for good looks */
  1025.     ResizeListBox_LB(gMonitorLB, &tempRect);
  1026.     
  1027.     SizeWindow(gMonitorWindow,
  1028.                tempRect.right - tempRect.left - 2,        /* -2 for borders */
  1029.                tempRect.bottom - tempRect.top - 2,
  1030.                FALSE);
  1031.                
  1032.     /* Since we know the size of the window, let's set the zoomRect and growRect */
  1033.     gZoomRect = gMonitorWindow->portRect;
  1034. /*    OffsetRect(&gZoomRect, - */
  1035.     SetRect(&gZoomRect,
  1036.             tempRect.right - tempRect.left - 2,
  1037.             50,
  1038.             tempRect.right - tempRect.left - 2,
  1039.             350);
  1040.     (*((WStateData **)(((WindowPeek)gMonitorWindow)->dataHandle)))->stdState = gZoomRect;
  1041.     
  1042.     SetRect(&gGrowRect,
  1043.             tempRect.right - tempRect.left - 1,
  1044.             80,
  1045.             tempRect.right - tempRect.left - 1,
  1046.             screenBits.bounds.bottom - screenBits.bounds.top);
  1047.             
  1048.     /* Since a new list box has drawing off, let's turn drawing on */
  1049.     CalcMonitorWindow();
  1050.     
  1051.     /* Move the window to the default position or center it if the default position doesn't */
  1052.     /* exist or the default position would otherwise take the window off screen. */
  1053.     
  1054.     if (!gSavePrefs ||
  1055.         ((gMonitorWindPt.h == 0) &&
  1056.         (gMonitorWindPt.v == 0) ||
  1057.         (gMonitorWindPt.h < 5) ||
  1058.         (gMonitorWindPt.h > (screenBits.bounds.right - 5)) ||
  1059.         (gMonitorWindPt.v < (MBarHeight + 25)) ||
  1060.         (gMonitorWindPt.v > (screenBits.bounds.bottom - 5))))
  1061.             CenterDialog(gMonitorWindow);
  1062.     else
  1063.         MoveWindow(gMonitorWindow, gMonitorWindPt.h, gMonitorWindPt.v, TRUE);
  1064.         
  1065.     ListBoxState_LB(gMonitorLB, LB_DrawOn);
  1066.     ShowWindow(gMonitorWindow);
  1067.     }
  1068.     
  1069. /********************************************************************************/
  1070. /*                                                                                */
  1071. /* This routine will allow the user to launch other applications from this        */
  1072. /* program.                                                                        */
  1073. /*                                                                                */
  1074. /********************************************************************************/
  1075.  
  1076. void HandleLaunchApp(void)
  1077.  
  1078.     {
  1079.     LaunchParamBlockRec        launchParms;
  1080.     StandardFileReply        theFileReply;
  1081.     SFTypeList                typeList;
  1082.     
  1083.     typeList[0] = 'APPL';        /* Launch only applications */
  1084.     typeList[1] = 'FNDR';        /* and the Finder (maybe the user quit it!) */
  1085.     
  1086.     StandardGetFile(NULL, 2, &typeList, &theFileReply);
  1087.     if (theFileReply.sfGood)
  1088.         {
  1089.         launchParms.launchBlockID = extendedBlock;
  1090.         launchParms.launchEPBLength = extendedBlockLen;
  1091.         launchParms.launchFileFlags = 0;
  1092.         launchParms.launchControlFlags = launchContinue + launchNoFileFlags;
  1093.         launchParms.launchAppSpec = &theFileReply.sfFile;
  1094.         launchParms.launchAppParameters = NULL;
  1095.         
  1096.         LaunchApplication(&launchParms);
  1097.         }
  1098.     }
  1099.     
  1100. /********************************************************************************/
  1101. /*                                                                                */
  1102. /* This routine will display the "About..." dialog.                                */
  1103. /*                                                                                */
  1104. /********************************************************************************/
  1105.  
  1106. void HandleAboutDialog(void)
  1107.  
  1108.     {
  1109.     DialogPtr        theDialog;
  1110.     int                itemHit;
  1111.     
  1112.     theDialog = GetNewDialog(ABOUT_DLOG_ID, NULL, (WindowPtr)-1);
  1113.     if (theDialog == NULL)
  1114.         {
  1115.         DisplayAlert(BAD_RESOURCES, STOP_ALERT, NULL);
  1116.         return;
  1117.         }
  1118.         
  1119.     CenterDialog(theDialog);
  1120.     ShowWindow(theDialog);
  1121.     
  1122.     do
  1123.         {
  1124.         ModalDialog(&GenericDialogFilter, &itemHit);
  1125.         }
  1126.     while (itemHit != OK);
  1127.     
  1128.     DisposeDialog(theDialog);
  1129.     }
  1130.     
  1131. /********************************************************************************/
  1132. /*                                                                                */
  1133. /* This routine will display and handle the "Preferences..." menu selection/    */
  1134. /* dialog.                                                                        */
  1135. /*                                                                                */
  1136. /********************************************************************************/
  1137.  
  1138. void HandlePreferencesDialog(void)
  1139.  
  1140.     {
  1141.     DialogPtr        theDialog;
  1142.     int                itemHit, tempInt;
  1143.     float            tempFloat;
  1144.     char            tempStr[256];
  1145.     
  1146.     theDialog = GetNewDialog(PREFS_DLOG_ID, NULL, (WindowPtr)-1);
  1147.     if (theDialog == NULL)
  1148.         {
  1149.         DisplayAlert(BAD_RESOURCES, STOP_ALERT, NULL);
  1150.         return;
  1151.         }
  1152.         
  1153.     /* Fill in the current refresh value */
  1154.     tempFloat = (float)gRefreshRate;
  1155.     tempFloat /= TICKS_PER_SECOND;
  1156.     sprintf(tempStr, "%3.1f", tempFloat);
  1157.     SetItemText(theDialog, PREF_REFRESH_ITEM, tempStr);        /* From "dialoglib" */
  1158.     SelIText(theDialog, PREF_REFRESH_ITEM, 0, 32767);        /* Select the entire item */
  1159.     
  1160.     /* Set the default window checkbox */
  1161.     SetCheckBox(theDialog, PREF_DEF_WINDOW, gOpenDefWindow);
  1162.     SetCheckBox(theDialog, PREF_AUTO_UPDATE, gAutoUpdate);
  1163.     SetCheckBox(theDialog, PREF_HIDE_IN_BACK, gHideInBackground);
  1164.     SetCheckBox(theDialog, PREF_SAVE_PREFS, gSavePrefs);
  1165.     
  1166.     CenterDialog(theDialog);
  1167.     ShowWindow(theDialog);
  1168.     
  1169.     do
  1170.         {
  1171.         ModalDialog(&GenericDialogFilter, &itemHit);
  1172.         
  1173.         switch (itemHit)
  1174.             {
  1175.             case PREF_DEF_WINDOW:
  1176.             case PREF_AUTO_UPDATE:
  1177.             case PREF_HIDE_IN_BACK:
  1178.             case PREF_SAVE_PREFS:
  1179.                 ToggleCheckBox(theDialog, itemHit, &tempInt);
  1180.                 break;
  1181.             }
  1182.         }
  1183.     while ((itemHit != OK) && (itemHit != Cancel));
  1184.     
  1185.     if (itemHit == OK)
  1186.         {
  1187.         /* GetItemTextLen() is from "dialoglib".  Get the text the user entered. */
  1188.         /* If it is valid, use it, otherwise keep the old. */
  1189.         
  1190.         /* Get the refresh time and verify it is valid */
  1191.         GetItemTextLen(theDialog, PREF_REFRESH_ITEM, tempStr, 3);    /* Only 3 decimal places */
  1192.         sscanf(tempStr, "%f", &tempFloat);
  1193.         tempFloat *= TICKS_PER_SECOND;
  1194.         
  1195.         if ((tempFloat >= MIN_REFRESH_RATE) &&
  1196.             (tempFloat <= MAX_REFRESH_RATE))
  1197.                 {
  1198.                 gRefreshRate = tempFloat;
  1199.                 WriteRes(&gRefreshRate);
  1200.                 }
  1201.                 
  1202.         /* Save the preferences */
  1203.         gOpenDefWindow = GetCheckBox(theDialog, PREF_DEF_WINDOW);
  1204.         WriteRes(&gOpenDefWindow);
  1205.         gAutoUpdate = GetCheckBox(theDialog, PREF_AUTO_UPDATE);
  1206.         WriteRes(&gAutoUpdate);
  1207.         gHideInBackground = GetCheckBox(theDialog, PREF_HIDE_IN_BACK);
  1208.         WriteRes(&gHideInBackground);
  1209.         gSavePrefs = GetCheckBox(theDialog, PREF_SAVE_PREFS);
  1210.         WriteRes(&gSavePrefs);
  1211.         }
  1212.         
  1213.     DisposeDialog(theDialog);
  1214.     }
  1215.     
  1216. /********************************************************************************/
  1217. /*                                                                                */
  1218. /* This routine will display a dialog of information about the process with the    */
  1219. /* process serial number thePSN.  It has to break down and digest the process    */
  1220. /* information record.                                                            */
  1221. /*                                                                                */
  1222. /* Input:    thePSN    = The process serial number of the process to display info    */
  1223. /*                      for.                                                        */
  1224. /*                                                                                */
  1225. /* Output:    None.                                                                */
  1226. /*                                                                                */
  1227. /********************************************************************************/
  1228.  
  1229. void HandleProcessInfoDialog(ProcessSerialNumber *thePSN)
  1230.  
  1231.     {
  1232.     DialogPtr        theDialog;
  1233.     int                itemHit;
  1234.     Str255            procName, otherName;
  1235.     ProcessInfoRec    theProcInfo, otherProcInfo;
  1236.     char            tempStr[256];
  1237.     FSSpec            locationName;
  1238.     
  1239.     theDialog = GetNewDialog(INFO_DLOG_ID, NULL, (WindowPtr)-1);
  1240.     if (theDialog == NULL)
  1241.         {
  1242.         DoAlert(STOP_ALERT, BAD_RESOURCES, "");
  1243.         return;
  1244.         }
  1245.         
  1246.     /* Get the process information and fill in the dialog items */
  1247.     SetWatchCursor();
  1248.     
  1249.     /* Prepare and then get the process information */
  1250.     theProcInfo.processInfoLength = sizeof(ProcessInfoRec);
  1251.     theProcInfo.processName = procName;
  1252.     theProcInfo.processAppSpec = &locationName;
  1253.     if (GetProcessInformation(thePSN, &theProcInfo) != noErr)
  1254.         {
  1255.         InitCursor();
  1256.         DoAlert(NOTE_ALERT, STR_APP_NOT_FOUND, "");
  1257.         return;
  1258.         }
  1259.         
  1260.     /* Fill in the main/easy items in the dialog with info from the process record */
  1261.     strcpy(tempStr, PtoCstr((char *)theProcInfo.processName));
  1262.     SetItemText(theDialog, INFO_NAME, tempStr);
  1263.     sprintf(tempStr, "%08ld/%08ld", theProcInfo.processNumber.highLongOfPSN,
  1264.             theProcInfo.processNumber.lowLongOfPSN);
  1265.     SetItemText(theDialog, INFO_PSN, tempStr);
  1266.     sprintf(tempStr, "'%4.4s'", (char *)&theProcInfo.processType);
  1267.     SetItemText(theDialog, INFO_TYPE, tempStr);
  1268.     sprintf(tempStr, "'%4.4s'", (char *)&theProcInfo.processSignature);
  1269.     SetItemText(theDialog, INFO_SIGNATURE, tempStr);
  1270.     sprintf(tempStr, "$%lX", theProcInfo.processLocation);
  1271.     SetItemText(theDialog, INFO_ADDRESS, tempStr);
  1272.     sprintf(tempStr, "%ld bytes (%ldK)", theProcInfo.processSize, (theProcInfo.processSize / 1024));
  1273.     SetItemText(theDialog, INFO_SIZE, tempStr);
  1274.     sprintf(tempStr, "%ld bytes (%ldK)", theProcInfo.processFreeMem, (theProcInfo.processFreeMem / 1024));
  1275.     SetItemText(theDialog, INFO_FREEMEM, tempStr);
  1276.     sprintf(tempStr, "%lu ticks", theProcInfo.processLaunchDate);
  1277.     SetItemText(theDialog, INFO_DATE, tempStr);
  1278.     sprintf(tempStr, "%lu ticks", theProcInfo.processActiveTime);
  1279.     SetItemText(theDialog, INFO_CPU_TIME, tempStr);
  1280.     
  1281.     /* Get the name of the launching/parent process */
  1282.     otherProcInfo.processInfoLength = sizeof(ProcessInfoRec);
  1283.     otherProcInfo.processName = otherName;
  1284.     otherProcInfo.processAppSpec = NULL;
  1285.     if (GetProcessInformation(&theProcInfo.processLauncher, &otherProcInfo) == noErr)
  1286.         {
  1287.         strcpy(tempStr, PtoCstr((char *)otherProcInfo.processName));
  1288.         SetItemText(theDialog, INFO_LAUNCHER, tempStr);
  1289.         }
  1290.     else
  1291.         SetItemText(theDialog, INFO_LAUNCHER, "Unknown");
  1292.         
  1293.     /* Get the file location */
  1294.     /* This item is not shown in the dialog, the staticText item is out of visRgn. */
  1295.     SetItemText(theDialog, INFO_LOCATION, PtoCstr(theProcInfo.processAppSpec->name));
  1296.     
  1297.     /* Set the bit fields from the 'SIZE' resource (theProcInfo.Mode field) */
  1298.     SetCheckBox(theDialog, INFO_DA, (theProcInfo.processMode & modeDeskAccessory));
  1299.     SetCheckBox(theDialog, INFO_MULTI_LAUNCH, (theProcInfo.processMode & modeMultiLaunch));
  1300.     SetCheckBox(theDialog, INFO_SUSPEND_RESUME, (theProcInfo.processMode & modeNeedSuspendResume));
  1301.     SetCheckBox(theDialog, INFO_CAN_BACKGROUND, (theProcInfo.processMode & modeCanBackground));
  1302.     SetCheckBox(theDialog, INFO_ACTIVATE_FGSWITCH, (theProcInfo.processMode & modeDoesActivateOnFGSwitch));
  1303.     SetCheckBox(theDialog, INFO_ONLY_BACKGROUND, (theProcInfo.processMode & modeOnlyBackground));
  1304.     SetCheckBox(theDialog, INFO_GET_FRONT_CLICKS, (theProcInfo.processMode & modeGetFrontClicks));
  1305.     SetCheckBox(theDialog, INFO_GET_APP_DIED_EVT, (theProcInfo.processMode & modeGetAppDiedMsg));
  1306.     SetCheckBox(theDialog, INFO_32BIT_COMPATIBLE, (theProcInfo.processMode & mode32BitCompatible));
  1307.     SetCheckBox(theDialog, INFO_HLEVENT_AWARE, (theProcInfo.processMode & modeHighLevelEventAware));
  1308.     SetCheckBox(theDialog, INFO_LOCAL_REMOTE_HLE, (theProcInfo.processMode & modeLocalAndRemoteHLEvents));
  1309.     SetCheckBox(theDialog, INFO_STATIONERY_AWARE, (theProcInfo.processMode & modeStationeryAware));
  1310.     SetCheckBox(theDialog, INFO_TEXTEDIT_SERVICES, (theProcInfo.processMode & modeUseTextEditServices));
  1311.     
  1312.     /* And get the system to display the current System Software */
  1313.     if ((globalSystemVers & 0x000F) == 0)        /* Test bug fix version */
  1314.         {
  1315.         sprintf(tempStr, "%d.%0d",
  1316.                 ((globalSystemVers & 0x0000FF00) >> 8),
  1317.                 ((globalSystemVers & 0x000000F0) >> 4));
  1318.         }
  1319.     else    /* A third (bug) version number must exist, let's add it in */
  1320.         {
  1321.         sprintf(tempStr, "%d.%0d.%d",
  1322.                 ((globalSystemVers & 0x0000FF00) >> 8),
  1323.                 ((globalSystemVers & 0x000000F0) >> 4),
  1324.                 (globalSystemVers & 0x0000000F));
  1325.         }
  1326.     SetItemText(theDialog, INFO_SYSTEM, tempStr);
  1327.     
  1328.     /* And let's clean things up and display the dialog */
  1329.     InitCursor();
  1330.     CenterDialog(theDialog);
  1331.     ShowWindow(theDialog);
  1332.     
  1333.     /* Handle dialog events */
  1334.     do
  1335.         {
  1336.         ModalDialog(&GenericDialogFilter, &itemHit);
  1337.         }
  1338.     while (itemHit != OK);
  1339.     
  1340.     /* And clean up! */
  1341.     DisposeDialog(theDialog);
  1342.     }
  1343.     
  1344. /********************************************************************************/
  1345. /*                                                                                */
  1346. /* This routine checks to make sure things are OK for getting the correct        */
  1347. /* number of parameters in the Apple Event.                                        */
  1348. /*                                                                                */
  1349. /********************************************************************************/
  1350.  
  1351. OSErr MyGotRequiredParams(AppleEvent *theAE)
  1352.  
  1353.     {
  1354.     DescType    returnedType;
  1355.     Size        actualSize;
  1356.     OSErr        err;
  1357.     
  1358.     /* Check for next parameter in the Apple Event */
  1359.     err = AEGetAttributePtr(theAE, keyMissedKeywordAttr, typeWildCard, &returnedType,
  1360.                             NULL, 0L, &actualSize);
  1361.                             
  1362.     if (err == errAEDescNotFound)    /* Are there no more parameters? */
  1363.         err = noErr;
  1364.         
  1365.     return(err);
  1366.     }
  1367.     
  1368. /********************************************************************************/
  1369. /*                                                                                */
  1370. /* This routine calculates the size of the window based on the size of the list    */
  1371. /* box.                                                                            */
  1372. /*                                                                                */
  1373. /* Input:    height    = Height of window.                                            */
  1374. /*            width    = Width of window.                                            */
  1375. /*                                                                                */
  1376. /********************************************************************************/
  1377.  
  1378. void ResizeMonitorWindow(int height, int width)
  1379.  
  1380.     {
  1381.     GrafPtr        oldPort;
  1382.     Rect        theLBrect;
  1383.     
  1384.     /* Let's turn off drawing for the listbox so it doesn't */
  1385.     /* draw while we are resizing the window.  We need to */
  1386.     /* resize the listbox to the size of the new window, but */
  1387.     /* then we need to size the window to that of the listbox */
  1388.     /* because the listbox is constrained due to the font. */
  1389.     /* Use -1 so listbox borders are outside, use +2 to count */
  1390.     /* the borders that are outside. */
  1391.     
  1392.     ListBoxState_LB(gMonitorLB, LB_DrawOff);
  1393.     
  1394.     theLBrect = gMonitorWindow->portRect;
  1395.     SetRect(&theLBrect,
  1396.             0,
  1397.             0,
  1398.             -1 + width + 2,
  1399.             -1 + height + 2);
  1400.             
  1401.     InsetRect(&theLBrect, -1, -1);
  1402.     ResizeListBox_LB(gMonitorLB, &theLBrect);
  1403.     GetRect_LB(gMonitorLB, &theLBrect);
  1404.     
  1405.     /* We use "-2" since the listbox borders are outside */
  1406.     /* the window and we are using the size of the listbox. */
  1407.     
  1408.     SizeWindow(gMonitorWindow,
  1409.                theLBrect.right - theLBrect.left - 2,
  1410.                theLBrect.bottom - theLBrect.top - 2,
  1411.                TRUE);
  1412.                
  1413.     /* Let's force an update event on ourself. */
  1414.     GetPort(&oldPort);
  1415.     SetPort(gMonitorWindow);
  1416.     InvalRect(&gMonitorWindow->portRect);
  1417.     SetPort(oldPort);
  1418.     
  1419.     /* Save window size if used in preferences */
  1420.     gWindowHeight = gMonitorWindow->portRect.bottom - gMonitorWindow->portRect.top;
  1421.     WriteRes(&gWindowHeight);
  1422.     
  1423.     ListBoxState_LB(gMonitorLB, LB_DrawOn);
  1424.     }
  1425.     
  1426. /********************************************************************************/
  1427. /*                                                                                */
  1428. /* This routine calculates the values and fills in the list box for the            */
  1429. /* monitor processes listbox (gMonitorLB).  This routine does not draw the        */
  1430. /* window or listbox.                                                            */
  1431. /*                                                                                */
  1432. /********************************************************************************/
  1433.  
  1434. void CalcMonitorWindow(void)
  1435.  
  1436.     {
  1437.     ProcessInfoRec            theProcInfo;
  1438.     ProcessSerialNumber        thePSN, selectedPSN;
  1439.     Str255                    procName;
  1440.     char                    tempStr[256];
  1441.     int                        i;
  1442.     
  1443.     if (gMonitorLB == NULL)
  1444.         return;
  1445.         
  1446.     /* Let's remember the selected process.  If it still exists after we */
  1447.     /* rebuild the listbox, let's set it to be the selected process again. */
  1448.     
  1449.     if (GetSelected_LB(gMonitorLB) != LB_NoneSelected)
  1450.         selectedPSN = PSNs[GetSelected_LB(gMonitorLB)];
  1451.     else
  1452.         {
  1453.         selectedPSN.lowLongOfPSN = kNoProcess;
  1454.         selectedPSN.highLongOfPSN = kNoProcess;
  1455.         }
  1456.         
  1457.     ListBoxState_LB(gMonitorLB, LB_DrawOff);
  1458.     EmptyListBox_LB(gMonitorLB);
  1459.     
  1460.     thePSN.lowLongOfPSN = kNoProcess;        /* Used to get first process in list */
  1461.     thePSN.highLongOfPSN = kNoProcess;
  1462.     
  1463.     i = 1;        /* Because the listbox starts at row 1, not 0 */
  1464.     
  1465.     /* While a process still exists... */
  1466.     while (GetNextProcess(&thePSN) != procNotFound)
  1467.         {
  1468.         /* Fill in parms for GetProcessInformation() */
  1469.         theProcInfo.processInfoLength = sizeof(ProcessInfoRec);
  1470.         theProcInfo.processName = procName;
  1471.         theProcInfo.processAppSpec = NULL;
  1472.         
  1473.         GetProcessInformation(&thePSN, &theProcInfo);
  1474.         
  1475.         /* Fill the listbox with this info */
  1476.         sprintf(tempStr, "%-21.21s  %4.4s  %4.4s  %08p %5ldK %5ldK",
  1477.                 PtoCstr((char *)theProcInfo.processName),
  1478.                 (char *)&theProcInfo.processType,
  1479.                 (char *)&theProcInfo.processSignature,
  1480.                 theProcInfo.processLocation,
  1481.                 (theProcInfo.processSize / 1024),
  1482.                 (theProcInfo.processFreeMem / 1024));
  1483.                 
  1484.         InsertRow_LB(gMonitorLB, LB_Append, tempStr, (long)i);
  1485.         PSNs[i++] = theProcInfo.processNumber;
  1486.         
  1487.         if (i >= MAX_PROCESSES)        /* Have we exceeded our array of PSNs? */
  1488.             break;
  1489.         }
  1490.         
  1491.     /* Set selected the process that was selected before the rebuild, if */
  1492.     /* one was selected.  We could have used memcpy() to compare the */
  1493.     /* structures, but I prefer comparing individual fields.  For a small */
  1494.     /* struct, there is really no time wasted, and it's clearer to the */
  1495.     /* reader what is really going on. */
  1496.     
  1497.     for (i=1; i<=GetNumRows_LB(gMonitorLB); i++)
  1498.         if ((PSNs[i].lowLongOfPSN == selectedPSN.lowLongOfPSN) &&
  1499.             (PSNs[i].highLongOfPSN == selectedPSN.highLongOfPSN))
  1500.                 {
  1501.                 SetSelected_LB(gMonitorLB, i, TRUE);
  1502.                 break;    /* We can only have one item selected */
  1503.                 }
  1504.                 
  1505.     ListBoxState_LB(gMonitorLB, LB_DrawOn);
  1506.     }
  1507.     
  1508. /********************************************************************************/
  1509. /*                                                                                */
  1510. /* This routine will display an alert of type alertType with 'STR#' resource of    */
  1511. /* stringID.  If stringID == 0, then text is used for the information.            */
  1512. /* DisplayAlert() is from the "dialoglib" library.                                */
  1513. /*                                                                                */
  1514. /* Input:    alertType    = STOP_ALERT, CAUTION_ALERT, or NOTE_ALERT.                */
  1515. /*            stringID    = 'STR#' resource string number.                        */
  1516. /*            text        = Optional text to put into alert (if stringID == 0).    */
  1517. /*                                                                                */
  1518. /********************************************************************************/
  1519.  
  1520. void DoAlert(int alertType, int stringID, char *text)
  1521.  
  1522.     {
  1523.     Str255        theString;
  1524.     
  1525.     if (stringID == 0)
  1526.         {
  1527.         strcpy((char *)theString, text);
  1528.         CtoPstr((char *)theString);
  1529.         }
  1530.     else
  1531.         {
  1532.         GetIndString(theString, ERROR_STRINGS_ID, stringID);
  1533.         if ((int)theString[0] == 0)
  1534.             {
  1535.             strcpy((char *)theString, "Critical error has occurred.  "
  1536.                                       "Program may be corrupted.  "
  1537.                                       "Advise program shutdown.");
  1538.             CtoPstr((char *)theString);
  1539.             }
  1540.         }
  1541.         
  1542.     ParamText(theString, "\p", "\p", "\p");
  1543.     DisplayAlert(ERROR_ALERT_ID, alertType, NULL);    /* dialoglib call */
  1544.     ParamText("\p", "\p", "\p", "\p");
  1545.     }
  1546.     
  1547. /********************************************************************************/
  1548. /*                                                                                */
  1549. /* This is a generic dialog filter.  It handles updates and keyDowns looking    */
  1550. /* for RETURN, ENTER, and ESCAPE keys.                                            */
  1551. /*                                                                                */
  1552. /********************************************************************************/
  1553.  
  1554. pascal Boolean GenericDialogFilter(DialogPtr theDialog, EventRecord *theEvent,
  1555.                                    int *theItem)
  1556.                                    
  1557.     {
  1558.     GrafPtr        oldPort;
  1559.     
  1560.     *theItem = 0;                        /* Initialize theItem */
  1561.     
  1562.     switch (theEvent->what)
  1563.         {
  1564.         case updateEvt:
  1565.             if ((WindowPtr)theEvent->message == theDialog)
  1566.                 {
  1567.                 GetPort(&oldPort);
  1568.                 SetPort(theDialog);
  1569.                 
  1570.                 BoldButton(theDialog, OK);
  1571.                 DrawDialogLines(theDialog);
  1572.                 
  1573.                 SetPort(oldPort);
  1574.                 }
  1575.             break;
  1576.             
  1577.         /* Test the RETURN and ENTER keys to see if the user pressed them */
  1578.         /* and if so, return OK as the item.  (if okFlag is TRUE!) */
  1579.         
  1580.         case keyDown:
  1581.             /* Check for special keys, try known ASCII characters */
  1582.             switch ((char)(theEvent->message & charCodeMask))
  1583.                 {
  1584.                 case RETURN_AKEY:
  1585.                 case ENTER_AKEY:
  1586.                     *theItem = OK;
  1587.                     return(TRUE);
  1588.                     break;
  1589.                     
  1590.                 case ESC_AKEY:
  1591.                     *theItem = Cancel;
  1592.                     return(TRUE);
  1593.                     break;
  1594.                 }
  1595.             break;
  1596.         }
  1597.         
  1598.     return(FALSE);
  1599.     }
  1600.     
  1601. /********************************************************************************/
  1602.